/**
  ******************************************************************************
  * @file    mg_driver_spi_master.c
  * @author  
  * @version V1.1
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2019 Shanghai Macrogiga Electronics</center></h2>
  *
  ******************************************************************************
  */

#include "mg_driver_spi_master.h"
#include "mg_driver_clock.h"

#define BLE_BIG_PACKAGE_SIZE /*255 buffer case supported*/

void SPIM_Init(SPIM_TypeInitDef* cfg)
{
    CLK_SetClockGate(CLK_GATE_SPIM_EN);
    
    SPIM->SSIENR = 0; //disable ssi
    
    SPIM->CTRLR0 = (cfg->RxTxMode) | (cfg->SCPOL) | (cfg->SCPH) | SPIM_FRF | SPIM_DFS;
    SPIM->BAUDR = cfg->SCK_DIV/* ^ 0x01*/; //spi clock = fc/div, div can only be 2,4,6,8,10,....
    SPIM->IMR = 0;//0x3F; //un-mask(disable) all int
    
    SPIM->TXFTLR = 1;
    SPIM->RXFTLR = 1;
    
    SPIM->SER = 1; //slave 0 is enabled
}

void SPIM_TxRxBuffer(u8* dataIn, u8*dataOut, u16 len)
{
    u16 i;
    __IO u32* des = SPIM_DATA_BASE;
    
    SPIM->CTRLR1 = len - 1;   //len
    SPIM->SSIENR = 1;         //start

    for(i = 0 ; i < len ; i ++)
    {        
        *des = *dataIn ++;        
//        while(SPIM->RXFLR == 0); //wait for tx done
//        *dataOut ++ = *(des); //read rx data        
//        while(SPIM->RXFLR != 0); //wait for rx done
    }
    
    //while(SPIM->SR & 0x01); //busy,    
    while(SPIM->RXFLR != len); //busy, all data are received.
    
    for(i = 0 ; i < len ; i ++)
    {
        *dataOut ++ = *(des); //read rx data
    }
    
    SPIM->SSIENR = 0; //clear    
}

#ifdef BLE_BIG_PACKAGE_SIZE //max255 bytes supported
void SPIM_TxBufferReg_s(u8 Cmd, u8* dataIn, u16 len) //max 31 bytes
{
    u16 i;
    __IO u32* des = SPIM_DATA_BASE;
    
    SPIM->CTRLR1 = len;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = Cmd;

    for(i = 0 ; i < len ; i ++)
    {        
        *des = *dataIn ++;
    }
       
    while(SPIM->RXFLR != (len+1)); //busy, all data are received.
    
    SPIM->SSIENR = 0; //clear
}

void SPIM_TxBufferReg(u8 Cmd, u8* dataIn, u16 len)
{
    u16 i,Total_Len;
    __IO u32* des = SPIM_DATA_BASE;
    __IO u8 t;
    
    if(len <= 31)
    {
        SPIM_TxBufferReg_s(Cmd,dataIn,len);
        return;
    }
    
    SPIM->CTRLR1 = len;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = Cmd;    
    while(SPIM->RXFLR != (1)); //busy, all data are received.
    t = *(des); //read rx data
    
    Total_Len = len;
    while(Total_Len)
    {
        len = Total_Len;
        if(len > 32)len = 32;
    
        for(i = 0 ; i < len ; i ++)
        {        
            *des = *dataIn ++;
        }
           
        while(SPIM->RXFLR != (len)); //busy, all data are received.        
        //for(i = 0 ; i < len ; i ++)t = *(des); //read rx data
        for(i = 0 ; i < 8 ; i ++){t = *(des); t = *(des);t = *(des);t = *(des);} //read rx data
        
        Total_Len -= len;
    }
    
    SPIM->SSIENR = 0; //clear
}

void SPIM_RxBufferReg_s(u8 Cmd, u8* dataOut, u16 len) //max 31 bytes
{
    u16 i;
    __IO u32* des = SPIM_DATA_BASE;
    
    SPIM->CTRLR1 = len;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = Cmd;

    for(i = 0 ; i < len ; i ++)
    {        
        *des = 0xff;
    }
       
    while(SPIM->RXFLR != (len+1)); //busy, all data are received.
    
    i = *(des); //read rx data cmd
    for(i = 0 ; i < len ; i ++)
    {
        *dataOut ++ = *(des); //read rx data
    }
    
    SPIM->SSIENR = 0; //clear
}

void SPIM_RxBufferReg(u8 Cmd, u8* dataOut, u16 len) //rx big number of bytes
{
    u16 i,Total_len;
    __IO u32* des = SPIM_DATA_BASE;
    __IO u8 t;
    
    if(len <= 31)
    {
        SPIM_RxBufferReg_s(Cmd,dataOut,len);
        return;
    }
    
    SPIM->CTRLR1 = len;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = Cmd;
    while(SPIM->RXFLR != (1)); //busy, all data are received.
    t = *(des); //read rx data

    Total_len = len;
    
    while(Total_len)
    {
        len = Total_len;
        if(len > 32)len = 32;
        
        for(i = 0 ; i < len ; i ++)
        {        
            *des = 0xff;
        }
           
        while(SPIM->RXFLR != (len)); //busy, all data are received.        
        
        for(i = 0 ; i < len ; i ++)
        {
            *dataOut ++ = *(des); //read rx data
        }
        
        Total_len -= len;
    }
    
    SPIM->SSIENR = 0; //clear
}

#else //max 31 bytes supported
void SPIM_TxBufferReg(u8 Cmd, u8* dataIn, u16 len)
{
    u16 i;
    __IO u32* des = SPIM_DATA_BASE;
    
    SPIM->CTRLR1 = len;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = Cmd;

    for(i = 0 ; i < len ; i ++)
    {        
        *des = *dataIn ++;
    }
       
    while(SPIM->RXFLR != (len+1)); //busy, all data are received.
    
    SPIM->SSIENR = 0; //clear
}

void SPIM_RxBufferReg(u8 Cmd, u8* dataOut, u16 len)
{
    u16 i;
    __IO u32* des = SPIM_DATA_BASE;
    
    SPIM->CTRLR1 = len;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = Cmd;

    for(i = 0 ; i < len ; i ++)
    {        
        *des = 0xff;
    }
       
    while(SPIM->RXFLR != (len+1)); //busy, all data are received.
    
    i = *(des); //read rx data cmd
    for(i = 0 ; i < len ; i ++)
    {
        *dataOut ++ = *(des); //read rx data
    }
    
    SPIM->SSIENR = 0; //clear
}
#endif

u8 SPIM_TxRxReg(u8 CmdReg, u8 Value)
{
    u8 rv;
    __IO u32* des = SPIM_DATA_BASE;
    
    SPIM->CTRLR1 = 1;   //len + cmd
    SPIM->SSIENR = 1;         //start
    
    *des = CmdReg;
    *des = Value;
       
    while(SPIM->RXFLR != 2); //busy, all data are received.
    
    Value = *(des); //read rx data cmd    
    rv = *(des); //read rx data
    
    SPIM->SSIENR = 0; //clear
    
    return rv;
}
